package com.bubblegumproject.ogo.component;

import net.sf.cglib.proxy.MethodProxy;

import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

/**
 * Contextual data for the invocation of a Component method.
 *
 * @author Azubuko Obele (buko.obele@gmail.com)
 */
public class InvocationContext {

    private ComponentInvocation invocation;

    private Object target;

    private Object[] parameters;

    private MethodProxy methodProxy;

    private Map<String, Object> contextData = new HashMap<String, Object>();

    private Iterator<Interceptor> currentInterceptor;

    public InvocationContext(ComponentInvocation invocation, Object target, MethodProxy method, Object... parameters) {
        this.invocation = invocation;
        this.target = target;
        this.methodProxy = method;
        this.parameters = parameters;
    }

    public ComponentInvocation getInvocation() {
        return invocation;
    }

    public Object getTarget() {
        return target;
    }

    public MethodProxy getMethodProxy() {
        return methodProxy;
    }

    public Object[] getParameters() {
        return parameters;
    }

    public void setParameters(Object[] newArgs) {
        this.parameters = newArgs;
    }

    public Map<String, Object> getContextData() {
        return contextData;
    }

    public Object proceed() throws Throwable {
        if (currentInterceptor == null) currentInterceptor = invocation.getInterceptors().iterator();

        if (currentInterceptor.hasNext()) {
            Interceptor interceptor = currentInterceptor.next();
            return interceptor.execute(this);
        } else {
            return methodProxy.invokeSuper(target, parameters);
        }
    }

    public String toString() {
        return "[" + getClass().getSimpleName() + "invocation=" + invocation + " target=" + target +
                " methodProxy=" + methodProxy.getSuperName() + " parameters=" + parameters +
                " contextData=" + contextData + "]";
    }
}
